﻿using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Presentation;
using PPTHelper.BLL.TimingRoot;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PPTHelper.BLL.TimingRoot
{
    /// <summary>
    /// 动画时间节点容器构造器
    /// </summary>
    public class TimeNodeBuilder
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="timing"></param>
        public TimingRootContainer BuildTimingRoot(Timing timing)
        {
            if (timing == null)
                return null;

            var parallelTimeNode = timing.TimeNodeList?.ParallelTimeNode;

            //
            // 如果时序根下没有并行时间容器，则改Slide可能没有动画。因为tnLst节点下可以有多种类型的容器，目前版本只支持parallel容器。
            //
            if (parallelTimeNode == null)
                return null;

            // 目前所了解的是timeNodeList下的时间节点容器必须是时序根
            if (parallelTimeNode.CommonTimeNode?.NodeType == TimeNodeValues.TmingRoot)
            {
                TimingRootContainer timingRootContainer = new TimingRootContainer();
                timingRootContainer.CommonTimeNode = parallelTimeNode.CommonTimeNode;

                // 构建子节点列表
                BuildTimeNodeList(timingRootContainer.CommonTimeNode.ChildTimeNodeList, timingRootContainer);

                PrintRoot(timingRootContainer, string.Empty);

                return timingRootContainer;
            }

            return null;
        }

        void PrintRoot(TimeNodeContainer timeNode, string table)
        {
            Console.WriteLine(table + timeNode.GetType().Name);
            table += "\t";
            foreach (var item in timeNode.TimeNodeList)
            {
                if (item is ActionContainer action)
                {
                    //table += "\t";
                    Console.WriteLine(table + action.GetType().Name);
                    PrintRoot(action.CommonBehavior, table);
                }
                else
                if (item is TimeNodeContainer tnc)
                {
                    PrintRoot(tnc, table);
                }
            }
        }

        /// <summary>
        /// 构建一个序列时间容器
        /// </summary>
        /// <param name="sequenceTimeNode"></param>
        /// <param name="parent"></param>
        /// <returns></returns>
        private void BuildSequenceContainer(SequenceTimeNode sequenceTimeNode, TimeNodeContainer parent)
        {
            if (sequenceTimeNode == null)
                return;

            // 取出XML中有用的属性
            SequenceContainer sequenceContainer = new SequenceContainer()
            {
                Concurrent = sequenceTimeNode.Concurrent,
                PreviousAction = sequenceTimeNode.PreviousAction,
                NextAction = sequenceTimeNode.NextAction,
                CommonTimeNode = sequenceTimeNode.CommonTimeNode,
                PreviousConditionList = sequenceTimeNode.PreviousConditionList,
                NextConditionList = sequenceTimeNode.NextConditionList,

                Parent = parent
            };
            // 把子节点添加到父节点下
            parent.TimeNodeList.Add(sequenceContainer);

            var commonTimeNode = sequenceContainer.CommonTimeNode;
            BuildTimeNodeList(commonTimeNode.ChildTimeNodeList, sequenceContainer);
        }


        /// <summary>
        /// 构建一个并行时间容器
        /// </summary>
        /// <param name="parallelTimeNode"></param>
        /// <param name="parent"></param>
        /// <returns></returns>
        private void BuildParllelContainer(ParallelTimeNode parallelTimeNode, TimeNodeContainer parent)
        {
            if (parallelTimeNode == null)
                return;

            ParallelContainer parallelContainer = new ParallelContainer()
            {
                CommonTimeNode = parallelTimeNode.CommonTimeNode,
                Parent = parent
            };
            // 把子节点添加到父节点下
            parent.TimeNodeList.Add(parallelContainer);

            var commonTimeNode = parallelTimeNode.CommonTimeNode;
            BuildTimeNodeList(commonTimeNode.ChildTimeNodeList, parallelContainer);
        }

        /// <summary>
        /// 构建一个并行时间容器
        /// </summary>
        /// <param name="exclusiveTimeNode"></param>
        /// <param name="parent"></param>
        /// <returns></returns>
        private void BuildExclusiveContainer(ExclusiveTimeNode exclusiveTimeNode, TimeNodeContainer parent)
        {
            if (exclusiveTimeNode == null)
                return;

            ExclusiveContainer exclusiveContainer = new ExclusiveContainer()
            {
                CommonTimeNode = exclusiveTimeNode.CommonTimeNode,
                Parent = parent
            };
            // 把子节点添加到父节点下
            parent.TimeNodeList.Add(exclusiveContainer);

            var commonTimeNode = exclusiveTimeNode.CommonTimeNode;

            // 构建子容器
            BuildTimeNodeList(commonTimeNode.ChildTimeNodeList, exclusiveContainer);
        }

        /// <summary>
        /// 构建一个设置行为容器
        /// </summary>
        /// <param name="setBehavior"></param>
        /// <param name="parent"></param>
        /// <returns></returns>
        private void BuildSetBehaviorContainer(SetBehavior setBehavior, TimeNodeContainer parent)
        {
            if (setBehavior == null)
                return;

            SetBehaviorContainer exclusiveContainer = new SetBehaviorContainer()
            {
                ToVariantValue = setBehavior.ToVariantValue,
                CommonBehavior = BuildCommonBehaviorContainer(setBehavior.CommonBehavior),
                Parent = parent
            };
            // 把子节点添加到父节点下
            parent.TimeNodeList.Add(exclusiveContainer);
        }

        /// <summary>
        /// 构建一个Animate容器
        /// </summary>
        /// <param name="animate"></param>
        /// <param name="parent"></param>
        /// <returns></returns>
        private void BuildAnimateContainer(Animate animate, TimeNodeContainer parent)
        {
            if (animate == null)
                return;

            // 取出XML中的全部属性
            AnimateContainer animateContainer = new AnimateContainer()
            {
                By = animate.By,
                From = animate.From,
                To = animate.To,
                CalculationMode = animate.CalculationMode,
                ValueType = animate.ValueType,
                BounceEnd = animate.BounceEnd,
                TimeAnimateValueList = animate.TimeAnimateValueList,
                CommonBehavior = BuildCommonBehaviorContainer(animate.CommonBehavior),
               
                Parent = parent
            };
            // 把子节点添加到父节点下
            parent.TimeNodeList.Add(animateContainer);
        }

        /// <summary>
        /// 构建子节点容器列表
        /// </summary>
        /// <param name="childTimeNodeList"></param>
        /// <param name="parent"></param>
        private void BuildTimeNodeList(ChildTimeNodeList childTimeNodeList, TimeNodeContainer parent)
        {
            if (parent == null || childTimeNodeList == null)
                return;

            // 这里我为什么用if else 呢？
            // 考虑到子节点列表里万一出现不同类型的子节点呢？
            // 所以这里挨个类型扫描吧

            foreach (var element in childTimeNodeList.ChildElements)
            {
                if (element is ParallelTimeNode par)
                {
                    BuildParllelContainer(par, parent);
                }
                else
                if (element is SequenceTimeNode seq)
                {
                    BuildSequenceContainer(seq, parent);
                }
                else
                if (element is ExclusiveTimeNode excl)
                {
                    BuildExclusiveContainer(excl, parent);
                }
                else
                if (element is SetBehavior set)
                {
                    BuildSetBehaviorContainer(set, parent);
                }
                else
                if (element is Animate aniamte)
                {
                    BuildAnimateContainer(aniamte, parent);
                }
            }
        }

        private CommonBehaviorContainer BuildCommonBehaviorContainer(CommonBehavior commonBehavior)
        {
            // 属性拷贝
            // 为什么要感觉没必要的这一步呢？
            // 其实个人认为还是很有必要的，尽量还原PPT文件的模型，以便以后的扩展。
            CommonBehaviorContainer behaviorContainer = new CommonBehaviorContainer()
            {
                Additive = commonBehavior.Additive,
                Accumulate = commonBehavior.Accumulate,
                TransformType = commonBehavior.TransformType,
                From = commonBehavior.From,
                To = commonBehavior.To,
                By = commonBehavior.By,
                RuntimeContext = commonBehavior.RuntimeContext,
                Override = commonBehavior.Override,
                TargetElement = commonBehavior.TargetElement,
                AttributeNameList = commonBehavior.AttributeNameList,
                CommonTimeNode = commonBehavior.CommonTimeNode,
            };

            BuildTimeNodeList(commonBehavior.CommonTimeNode.ChildTimeNodeList, behaviorContainer);

            return behaviorContainer;
        }

        void Test()
        {
            //
            //
            //AnimateScale
        }
    }
}
